package com.stu.javabase;

/**
 * 面向对象编程特征演示
 * 演示面向对象编程的四大特征：封装、继承、多态、抽象
 * 
 * @author 学习者
 * @version 1.0
 */
public class OOPCharacteristics {
    
    public static void main(String[] args) {
        System.out.println("=== 面向对象编程特征演示 ===");
        
        // 1. 封装演示
        System.out.println("\n1. 封装特征演示：");
        OOPPerson person = new OOPPerson("张三", 25);
        System.out.println("姓名：" + person.getName());
        System.out.println("年龄：" + person.getAge());
        person.setAge(30);
        System.out.println("修改后年龄：" + person.getAge());
        
        // 2. 继承演示
        System.out.println("\n2. 继承特征演示：");
        OOPStudent student = new OOPStudent("李四", 20, "计算机科学");
        student.introduce(); // 继承父类方法
        student.study(); // 子类特有方法
        
        // 3. 多态演示
        System.out.println("\n3. 多态特征演示：");
        Animal dog = new Dog();
        Animal cat = new Cat();
        dog.makeSound(); // 运行时多态
        cat.makeSound(); // 运行时多态
        
        // 4. 抽象演示
        System.out.println("\n4. 抽象特征演示：");
        Shape circle = new Circle(5.0);
        Shape rectangle = new Rectangle(4.0, 6.0);
        System.out.println("圆形面积：" + circle.calculateArea());
        System.out.println("矩形面积：" + rectangle.calculateArea());
    }
}

/**
 * 封装特征演示类
 * 通过private修饰符隐藏内部实现，通过public方法提供访问接口
 */
class OOPPerson {
    // 私有属性，体现封装性
    private String name;
    private int age;
    
    /**
     * 构造方法
     * @param name 姓名
     * @param age 年龄
     */
    public OOPPerson(String name, int age) {
        this.name = name;
        this.setAge(age); // 使用setter方法，确保数据验证
    }
    
    /**
     * 获取姓名
     * @return 姓名
     */
    public String getName() {
        return name;
    }
    
    /**
     * 设置姓名
     * @param name 姓名
     */
    public void setName(String name) {
        this.name = name;
    }
    
    /**
     * 获取年龄
     * @return 年龄
     */
    public int getAge() {
        return age;
    }
    
    /**
     * 设置年龄，包含数据验证
     * @param age 年龄
     */
    public void setAge(int age) {
        if (age >= 0 && age <= 150) {
            this.age = age;
        } else {
            System.out.println("年龄设置无效，必须在0-150之间");
        }
    }
    
    /**
     * 自我介绍方法
     */
    public void introduce() {
        System.out.println("我是" + name + "，今年" + age + "岁");
    }
}

/**
 * 继承特征演示类
 * Student类继承OOPPerson类，获得父类的属性和方法
 */
class OOPStudent extends OOPPerson {
    private String major; // 专业
    
    /**
     * 构造方法
     * @param name 姓名
     * @param age 年龄
     * @param major 专业
     */
    public OOPStudent(String name, int age, String major) {
        super(name, age); // 调用父类构造方法
        this.major = major;
    }
    
    /**
     * 学习方法 - 子类特有方法
     */
    public void study() {
        System.out.println(getName() + "正在学习" + major);
    }
    
    /**
     * 重写父类的introduce方法，体现多态性
     */
    @Override
    public void introduce() {
        super.introduce();
        System.out.println("我的专业是" + major);
    }
}

/**
 * 多态特征演示 - 抽象动物类
 */
abstract class Animal {
    /**
     * 抽象方法 - 发出声音
     * 子类必须实现此方法
     */
    public abstract void makeSound();
    
    /**
     * 具体方法 - 睡觉
     */
    public void sleep() {
        System.out.println("动物在睡觉");
    }
}

/**
 * 狗类 - 继承Animal类
 */
class Dog extends Animal {
    /**
     * 实现抽象方法
     */
    @Override
    public void makeSound() {
        System.out.println("狗：汪汪汪！");
    }
}

/**
 * 猫类 - 继承Animal类
 */
class Cat extends Animal {
    /**
     * 实现抽象方法
     */
    @Override
    public void makeSound() {
        System.out.println("猫：喵喵喵！");
    }
}

/**
 * 抽象特征演示 - 抽象形状类
 */
abstract class Shape {
    /**
     * 抽象方法 - 计算面积
     * @return 面积
     */
    public abstract double calculateArea();
    
    /**
     * 抽象方法 - 计算周长
     * @return 周长
     */
    public abstract double calculatePerimeter();
}

/**
 * 圆形类
 */
class Circle extends Shape {
    private double radius;
    
    /**
     * 构造方法
     * @param radius 半径
     */
    public Circle(double radius) {
        this.radius = radius;
    }
    
    /**
     * 计算圆形面积
     * @return 面积
     */
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
    
    /**
     * 计算圆形周长
     * @return 周长
     */
    @Override
    public double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
}

/**
 * 矩形类
 */
class Rectangle extends Shape {
    private double width;
    private double height;
    
    /**
     * 构造方法
     * @param width 宽度
     * @param height 高度
     */
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    /**
     * 计算矩形面积
     * @return 面积
     */
    @Override
    public double calculateArea() {
        return width * height;
    }
    
    /**
     * 计算矩形周长
     * @return 周长
     */
    @Override
    public double calculatePerimeter() {
        return 2 * (width + height);
    }
}